package com.utils.date;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

/**
 * 日期工具类
 */
public class CalendarUtil {

	public static final String YEAR = "year";

	public static final String MONTH = "month";

	public static final String MONTH_FIRST_DAY_TIME = "month_first_day_time";

	public static final String MONTH_LAST_DAY_TIME = "month_last_day_time";

	/**
	 * 获取当前时间距离北京零点多少秒
	 */
	@SuppressWarnings("deprecation")
	public static int getNowSecond() {
		Date date = getBjDate();
		int seconds = date.getHours() * 3600 + date.getMinutes() * 60 + date.getSeconds();
		return seconds;

	}

	/**
	 * 获取北京时间日期
	 */
	public static Date getBjDate() {
		Calendar calendar = Calendar.getInstance(Locale.CHINA);
		Date date = calendar.getTime();
		return date;
	}

	/**
	 * 获取当前日期13位时间戳，精确到毫秒
	 */
	public static long getLongTime() {
		return getBjDate().getTime();
	}

	/**
	 * 获取当前日期11位时间戳，精确到秒
	 */
	public static int getShortTime() {

		return Integer.valueOf(String.valueOf(getLongTime()).substring(0, 10));
	}

	/**
	 * 秒时间戳转日期
	 */
	public static Date transSecondForDate(int timeStamp) {

		return new Date(timeStamp * 1000L);
	}

	/**
	 * 获取指定日期11位时间戳，精确到秒
	 */
	public static int getDateShortTime(Date date) {

		return Integer.valueOf(String.valueOf(date.getTime()).substring(0, 10));
	}

	/**
	 * 获取当前日期天时间戳
	 */
	public static int getDayTime() {
		return Integer.parseInt(DateUtil.COMPAT.getDateText(getBjDate()));
	}
	/**
	 * 获取指定日期天时间戳
	 */
	public static int getDayTime(Date date) {
		return Integer.parseInt(DateUtil.COMPAT.getDateText(date));
	}
	/**
	 * 获取指定日期字符串天时间戳
	 * @throws ParseException 
	 * @throws NumberFormatException 
	 */
	public static int getDayFromDateStr(String date) throws NumberFormatException, ParseException {
		return getDayTime(DateUtil.COMPAT.getTextDate(date));
	}
	/**
	 * 获取指定日期时间戳天
	 * @throws ParseException 
	 * @throws NumberFormatException 
	 */
	public static int getDayFromtimeStamp(int timeStamp) throws NumberFormatException, ParseException {
		Date date=transSecondForDate(timeStamp);
		return getDayTime(date);
	}
	/**
	 * 获取指定日期天时间戳
	 * @throws ParseException 
	 * @throws NumberFormatException 
	 */
	public static int getDayTime(String dateStr) throws NumberFormatException, ParseException {
		return getDayTime(DateUtil.COMMON.getTextDate(dateStr));
		// return (int) (getBjDate().getTime()/(1000*3600*24));
	}

	// 获取当前年的前n年数据
	public static List<String> getPreYears(int n) {
		List<String> years = new ArrayList<String>();
		Calendar calendar = Calendar.getInstance();
		int year = calendar.get(Calendar.YEAR);
		for (int i = 0; i < n; i++) {
			years.add((year - i) + "");
		}
		return years;
	}

	// 获取当前年的第n年后年份（n可为负数）
	public static Date getPreYear(Date date, int n) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.YEAR, n);
		return calendar.getTime();
	}

	// 指定时间前n小时的时间
	public static Date hourHeadDate(Date date, int hours) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.HOUR_OF_DAY, hours);
		return cal.getTime();
	}

	// 指定时间n分钟后的时间
	public static Date minHeadDate(Date date, int minutes) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.MINUTE, minutes);
		return cal.getTime();
	}

	// 获取12个月的数据
	public static List<String> get12MonthStr() {
		List<String> months = new ArrayList<String>();
		for (int i = 1; i < 13; i++) {
			months.add(i + "");
		}
		return months;
	}

	// 获取明天的日期
	public static String getNextDay(String format) {
		Calendar calendar = Calendar.getInstance();
		Calendar tmpCalendar = Calendar.getInstance();
		tmpCalendar.set(Calendar.DATE, calendar.getActualMaximum(Calendar.DATE));// 设置本月最大日期
		int maxDate = tmpCalendar.get(Calendar.DATE);

		int month = calendar.get(Calendar.MONTH);
		int year = calendar.get(Calendar.YEAR);
		int date = calendar.get(Calendar.DATE);

		if (date + 1 > maxDate) {
			if (month + 1 > 11) {
				calendar.add(Calendar.YEAR, 1);
				calendar.set(Calendar.MONTH, 0);
				calendar.set(Calendar.DATE, 1);
			} else {
				calendar.set(year, month, date + 1);
			}
		} else {
			calendar.set(year, month, date + 1);
		}
		return DateUtil.getDateText(calendar.getTime(), format);
	}

	// 获取n天后的日期,时分秒相同
	public static Date getNextNDay(Date startTime, Integer n) {
		Calendar start = Calendar.getInstance();
		start.setTime(startTime);
		start.add(Calendar.DATE, n);
		return start.getTime();
	}

	// 获取指定日期00:00:00时刻的n天后日期
	public static Date getNextNDayBegin(Date startTime, Integer n) {
		Calendar start = Calendar.getInstance();
		start.setTime(startTime);
		start.add(Calendar.DATE, n);
		start.set(Calendar.HOUR_OF_DAY, 0);
		start.set(Calendar.MINUTE, 0);
		start.set(Calendar.SECOND, 0);
		return start.getTime();
	}
	



	// 获取指定日期23:59:59时刻的n天后日期
	public static Date getNextNDayEnd(Date startTime, Integer n) {
		Calendar start = Calendar.getInstance();
		start.setTime(startTime);
		start.add(Calendar.DATE, n);
		start.set(Calendar.HOUR_OF_DAY, 23);
		start.set(Calendar.MINUTE, 59);
		start.set(Calendar.SECOND, 59);
		return start.getTime();
	}
	
	// 获取指定字符串日期00:00:00时刻的n天后日期时间戳，精确到秒
	public static int getNextNDayStrBeginTime(String startTime, Integer n) throws ParseException {
		Date date=DateUtil.COMMON.getTextDate(startTime);
		Calendar start = Calendar.getInstance();
		start.setTime(date);
		start.add(Calendar.DATE, n);
		start.set(Calendar.HOUR_OF_DAY, 0);
		start.set(Calendar.MINUTE, 0);
		start.set(Calendar.SECOND, 0);
		return getDateShortTime(start.getTime());
	}
	



	// 获取指定字符串日期n天后23:59:59时刻的日期时间戳
	public static int getNextNDayStrEndTime(String startTime, Integer n) throws ParseException {
		Date date=DateUtil.COMMON.getTextDate(startTime);
		Calendar start = Calendar.getInstance();
		start.setTime(date);
		start.add(Calendar.DATE, n);
		start.set(Calendar.HOUR_OF_DAY, 23);
		start.set(Calendar.MINUTE, 59);
		start.set(Calendar.SECOND, 59);
		return getDateShortTime(start.getTime());
	}

	// 获取指定日期n天前的日期
	public static Date getPreNDay(Date startTime, Integer n) {
		Calendar start = Calendar.getInstance();
		start.setTime(startTime);
		start.add(Calendar.DATE, -n);
		return start.getTime();
	}

	// 获取指定日期00:00:00时刻的n天前日期
	public static Date getPreNDayBegin(Date startTime, Integer n) {
		Calendar start = Calendar.getInstance();
		start.setTime(startTime);
		start.add(Calendar.DATE, -n);
		start.set(Calendar.HOUR_OF_DAY, 0);
		start.set(Calendar.MINUTE, 0);
		start.set(Calendar.SECOND, 0);
		return start.getTime();
	}

	// 获取指定日期23:59:59时刻的n天前日期
	public static Date getPreNDayEnd(Date startTime, Integer n) {
		Calendar start = Calendar.getInstance();
		start.setTime(startTime);
		start.add(Calendar.DATE, -n);
		start.set(Calendar.HOUR_OF_DAY, 23);
		start.set(Calendar.MINUTE, 59);
		start.set(Calendar.SECOND, 59);
		return start.getTime();
	}

	// 获取当前日期前x天的日期
	public static String getPreXDay(int x, String format) {
		Calendar calendar = Calendar.getInstance();
		int month = calendar.get(Calendar.MONTH);
		int year = calendar.get(Calendar.YEAR);
		int date = calendar.get(Calendar.DATE);

		if (date - x < 0) {
			if (month - 1 < 0) {
				calendar.add(Calendar.YEAR, -1);
				calendar.set(Calendar.MONTH, 11);
				calendar.set(Calendar.DATE, 31 - (x - date));
			} else {
				calendar.add(Calendar.MONTH, -1);
				calendar.set(Calendar.DATE, calendar.getActualMaximum(Calendar.DATE));// 设置本月最大日期
				int maxDate = calendar.get(Calendar.DATE);
				calendar.set(year, month - 1, maxDate - (x - date));
			}
		} else {
			calendar.set(year, month, date - x);
		}
		return DateUtil.getDateText(calendar.getTime(), format);
	}

	// 获取当前年
	public static String getYear() {
		Calendar calendar = Calendar.getInstance();
		int year = calendar.get(Calendar.YEAR);
		return year + "";
	}

	// 获取当前月
	public static String getMonth() {
		Calendar calendar = Calendar.getInstance();
		int month = calendar.get(Calendar.MONTH);
		month = month + 1;
		if (month > 12) {
			return "12";
		}
		return month + "";
	}

	// 获取某年某月的第一天和最后一天时间
	public static Map<String, String> getMonthFirstEndDayTime(String year, String month) {
		Map<String, String> rst = new HashMap<String, String>();
		Calendar calendar = Calendar.getInstance();
		int m = Integer.parseInt(month);
		m = m - 1;
		if (m < 0) {
			m = 0;
		}
		calendar.set(Integer.parseInt(year), m, 1);
		String firstDayTime = DateUtil.COMMON.getDateText(calendar.getTime()) + " 00:00:00";

		calendar.set(Calendar.DATE, calendar.getActualMaximum(Calendar.DATE));// 设置本月最大日期
		String lastDayTime = DateUtil.COMMON.getDateText(calendar.getTime()) + " 23:59:59";

		rst.put(CalendarUtil.MONTH_FIRST_DAY_TIME, firstDayTime);
		rst.put(CalendarUtil.MONTH_LAST_DAY_TIME, lastDayTime);

		return rst;
	}

	// 获取指定日期的n个月后日期(负值则为之前n个月日期)
	public static Date getOffsetMonthDate(Date protoDate, int monthOffset) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(protoDate);
		cal.add(Calendar.MONTH, monthOffset); // 正确写法
		return cal.getTime();
	}

	// 获取当前月份的前一个月
	public static Map<String, String> getPreMonth() {
		Map<String, String> rst = new HashMap<String, String>();
		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.MONTH, -1);
		int year = calendar.get(Calendar.YEAR);
		int month = calendar.get(Calendar.MONTH);
		month = month + 1;

		rst.put("year", year + "");
		if (month > 12) {
			rst.put("month", "12");
		} else {
			rst.put("month", month + "");
		}
		return rst;
	}

	// 获取某年某月的前一个月
	public static Map<String, String> getPreMonth(Integer year, Integer month) {
		Map<String, String> rst = new HashMap<String, String>();
		if (month == 1) {
			rst.put("year", (year - 1) + "");
			rst.put("month", "12");
		} else {
			rst.put("year", year + "");
			rst.put("month", (month - 1) + "");
		}
		return rst;
	}

	// 获取开始月份和结束月份中间的所有月份，包括开始月份和结束月份
	public static List<String> getBetweenMonths(String startMonth, String endMonth) {
		String[] startArr = startMonth.split("-");
		String[] endArr = endMonth.split("-");

		Integer startY = Integer.parseInt(startArr[0]);
		Integer startM = Integer.parseInt(startArr[1]);

		Integer endY = Integer.parseInt(endArr[0]);
		Integer endM = Integer.parseInt(endArr[1]);

		Calendar startCalendar = Calendar.getInstance();
		startCalendar.set(startY, startM - 1, 1, 0, 0);

		Calendar endCalendar = Calendar.getInstance();
		endCalendar.set(endY, endM - 1, 1, 0, 0);

		List<String> months = new ArrayList<String>();
		while (startCalendar.getTimeInMillis() <= endCalendar.getTimeInMillis()) {
			months.add(DateUtil.getDateText(startCalendar.getTime(), "yyyy-MM"));
			startCalendar.add(Calendar.MONTH, 1);
		}
		return months;
	}

	// 获取日期之间的天List formt = "yyyy-MM-dd"
	public static List<String> getBetweenDateStr(String startTime, String endTime) {
		List<String> dateList = new ArrayList<String>();
		try {
			Long startM = DateUtil.COMMON.getTextDate(startTime).getTime();
			Long endM = DateUtil.COMMON.getTextDate(endTime).getTime();
			long result = (endM - startM) / (24 * 60 * 60 * 1000);
			String[] startTimeStr = startTime.split("-");
			Calendar startCalendar = Calendar.getInstance();
			startCalendar.set(Integer.parseInt(startTimeStr[0]), Integer.parseInt(startTimeStr[1]) - 1,
					Integer.parseInt(startTimeStr[2]));
			startCalendar.add(Calendar.DATE, -1);
			for (int i = 0; i <= result; i++) {
				startCalendar.add(Calendar.DATE, 1);
				dateList.add(DateUtil.COMMON.getDateText(startCalendar.getTime()));
			}
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return dateList;
	}

	// 获取日期之间的天List 输出指定日期格式
	public static List<String> getBetweenDateStr(String startTime, String endTime, String format) {
		List<String> dateList = new ArrayList<String>();
		try {
			Long startM = DateUtil.COMMON.getTextDate(startTime).getTime();
			Long endM = DateUtil.COMMON.getTextDate(endTime).getTime();
			long result = (endM - startM) / (24 * 60 * 60 * 1000);
			String[] startTimeStr = startTime.split("-");
			Calendar startCalendar = Calendar.getInstance();
			startCalendar.set(Integer.parseInt(startTimeStr[0]), Integer.parseInt(startTimeStr[1]) - 1,
					Integer.parseInt(startTimeStr[2]));
			startCalendar.add(Calendar.DATE, -1);
			for (int i = 0; i <= result; i++) {
				startCalendar.add(Calendar.DATE, 1);
				dateList.add(DateUtil.getDateText(startCalendar.getTime(), format));
			}
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return dateList;
	}

	// 获取当前日期的前n个月的月份集合（闭区间）
	public static List<String> getPreNMonths(String curMonth, Integer n) {
		String[] curArr = curMonth.split("-");
		Integer curY = Integer.parseInt(curArr[0]);
		Integer curM = Integer.parseInt(curArr[1]);

		Calendar curCalendar = Calendar.getInstance();
		curCalendar.set(curY, curM - 1, 1, 0, 0);

		Calendar tmpCalendar = Calendar.getInstance();
		tmpCalendar.set(curY, curM - 1 - n, 1, 0, 0);

		List<String> months = new ArrayList<String>();
		while (tmpCalendar.getTimeInMillis() <= curCalendar.getTimeInMillis()) {
			months.add(DateUtil.getDateText(tmpCalendar.getTime(), "yyyy-MM"));
			tmpCalendar.add(Calendar.MONTH, 1);
		}
		return months;
	}

	// 获取当前天
	public static String getToday(String format) {
		Calendar calendar = Calendar.getInstance();
		return DateUtil.getDateText(calendar.getTime(), format);
	}

	// 获取当前月的第一天
	public static String getFirstDay(String format) {
		Calendar calendar = Calendar.getInstance();
		int month = calendar.get(Calendar.MONTH);
		int year = calendar.get(Calendar.YEAR);
		calendar.set(year, month, 1);
		return DateUtil.getDateText(calendar.getTime(), format);
	}

	// 获取当前月的最后一天
	public static String getLastDay(String format) {
		Calendar calendar = Calendar.getInstance();
		calendar.set(Calendar.DATE, calendar.getActualMaximum(Calendar.DATE));// 设置本月最大日期
		return DateUtil.getDateText(calendar.getTime(), format);
	}

	// 获取指定日期月的第一天
	public static Date getFirstDayOfDate(String dateStr) throws ParseException {
		Date date=DateUtil.COMMON.getTextDate(dateStr);
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		int month = calendar.get(Calendar.MONTH);
		int year = calendar.get(Calendar.YEAR);
		calendar.set(year, month, 1);
		return calendar.getTime();
	}

	// 获取指定日期月的最后一天
	public static Date getLastDayOfDate(String dateStr) throws ParseException {
		Date date=DateUtil.COMMON.getTextDate(dateStr);
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.DATE, calendar.getActualMaximum(Calendar.DATE));// 设置本月最大日期
		return calendar.getTime();
	}

	// 获取当前月的第一天返回Date类型
	public static Date getFirstDate() {
		Calendar calendar = Calendar.getInstance();
		int month = calendar.get(Calendar.MONTH);
		int year = calendar.get(Calendar.YEAR);
		calendar.set(year, month, 1);
		return calendar.getTime();
	}

	// 获取当前月的最后一天返回Date类型
	public static Date getLastDate() {
		Calendar calendar = Calendar.getInstance();
		calendar.set(Calendar.DATE, calendar.getActualMaximum(Calendar.DATE));// 设置本月最大日期
		return calendar.getTime();
	}

	// 判断日期的天是否一样
	public static boolean isDayEqual(Date date1, Date date2) {
		if (date1 == null || date2 == null) {
			return false;
		}
		String date1Str = DateUtil.COMPAT.getDateText(date1);
		String date2Str = DateUtil.COMPAT.getDateText(date2);
		return date1Str.equals(date2Str);
	}

	/**
	 * 判断时间间距是否为xx毫秒； 如果在 space 之内返回true；否则返回false
	 * 
	 * @param startTime
	 *            开始时间
	 * @param endTime
	 *            结束时间
	 * @param space
	 *            毫秒
	 * @return
	 */
	public static boolean isTimeSpace(Date startTime, Date endTime, long space) {
		if (startTime == null || endTime == null) {
			return false;
		}
		return endTime.getTime() - startTime.getTime() <= space;
	}

	/**
	 * 判断时间间距是否在 startSpace 和 endSpace 之间
	 * 
	 * @param startTime
	 * @param endTime
	 * @param startSpace
	 * @param endSpace
	 * @return
	 */
	public static boolean isTimeBetween(Date startTime, Date endTime, long startSpace, long endSpace) {
		return endTime.getTime() - startTime.getTime() <= endSpace
				&& endTime.getTime() - startTime.getTime() >= startSpace;
	}

	/**
	 * 判断日期是否在startTime和endTime日期之间
	 * 
	 * @param time
	 * @param startTime
	 * @param endTime
	 */

	public static boolean isTimeBetween(Date time, Date startTime, Date endTime) {
		return time.getTime() >= startTime.getTime() && time.getTime() <= endTime.getTime();
	}

	// 获取日期之间相隔几年
	public static Integer getYearSpace(Date startTime, Date endTime) {
		Calendar start = Calendar.getInstance();
		start.setTime(startTime);
		Calendar end = Calendar.getInstance();
		end.setTime(endTime);
		return end.get(Calendar.YEAR) - start.get(Calendar.YEAR);
	}

	// 获取日期之间相隔几天
	public static Integer getDaySpace(Date startTime, Date endTime) {
		return (int) (endTime.getTime() - startTime.getTime()) / (24 * 60 * 60 * 1000);
	}

	// 获取时间戳之间相隔几天(单位秒,不包含当天)
	public static Integer getSampDaySpace(int startTime, int endTime) {
		return (int) (endTime - startTime) / (24 * 60 * 60);
	}

	// 获取日期之间相隔几秒
	public static Integer getDaySECOND(Date startTime, Date endTime) {
		return (int) (endTime.getTime() - startTime.getTime()) / 1000;
	}

	// 获取当前日期 毫秒或时间戳
	public static long getTimeInMillis() {
		Calendar now = Calendar.getInstance();
		return now.getTimeInMillis();
	}

	// 获取当前日期 秒
	public static long getTimeInSeconds() {
		return getTimeInMillis() / 1000L;
	}

}
